<?php


/**
*公钥 私钥的加解密
*/


class Rsa {
	static  $alg = OPENSSL_ALGO_MD5;

	static $publicKey = '';

	static $privateKey = '';

		 /**
     * rsa公钥验签
     * @param $keys
     */
    static function sign($str, $key = null, $alg = null)
    {
        //读取私钥文件
        $key = self::formatKey(self::$privateKey);
        $privkeyId = openssl_pkey_get_private($key);
        //$deail = openssl_pkey_get_details($privkeyId);
        //var_dump($deail);
        $result = openssl_sign($str,
         $signature, 
         $privkeyId, 
         self::$alg);
        openssl_free_key($privkeyId);
        return $signature;
        //return base64_encode($signature);
    }

	 /**
     * rsa公钥验签
     * @param $keys
     */
    static function verify($str, $signature, $key = null, $alg = null)
    {
        //读取密钥文件
        $key = self::formatKey(self::$publicKey, 1);
        $keyId = openssl_pkey_get_public($key);
        $result = openssl_verify($str,
         $signature, 
         $keyId, 
         self::$alg);
        openssl_free_key($keyId);
        return $result === 1 ? true : false;
        //return base64_encode($signature);
    }

    static function encrypt($data, $key = null)
    {
    	$key = self::formatKey(self::$publicKey, 1);
        $keyId = openssl_pkey_get_public($key);
        $maxlength = self::getMaxEncryptBlockSize($keyId);
        $output = '';
        while ($data) {
            $input = substr($data, 0, $maxlength);
            $data = substr($data, $maxlength);
            openssl_public_encrypt($input, $out, $keyId);
            $output .= $out;
        }
        openssl_free_key($keyId);
        //$output = bin2hex($output);
        return $output;
    }

    static function decrypt($data, $key = null)
    {
    	$key = self::formatKey(self::$privateKey);
        $keyId = openssl_pkey_get_private($key);
        $maxlength = self::getMaxDecryptBlockSize($keyId);
        $output = '';
        while ($data) {
            $input = substr($data, 0, $maxlength);
            $data = substr($data, $maxlength);
            openssl_private_decrypt($input, $out, $keyId);
            $output .= $out;
        }
        openssl_free_key($keyId);
        return $output;
    }


    static function encryptByPri($data, $key = null)
    {
    	$key = self::formatKey(self::$privateKey);
        $keyId = openssl_pkey_get_private($key);
        $maxlength = self::getMaxEncryptBlockSize($keyId);
        $output = '';
        while ($data) {
            $input = substr($data, 0, $maxlength);
            $data = substr($data, $maxlength);
            openssl_private_encrypt($input, $out, $keyId);
            $output .= $out;
        }
        openssl_free_key($keyId);
        //$output = bin2hex($output);
        return $output;
    }

    static function decryptByPub($data, $key = null)
    {
    	$key = self::formatKey(self::$publicKey, 1);
        $keyId = openssl_pkey_get_public($key);
        $maxlength = self::getMaxDecryptBlockSize($keyId);
        $output = '';
        while ($data) {
            $input = substr($data, 0, $maxlength);
            $data = substr($data, $maxlength);
            openssl_public_decrypt($input, $out, $keyId);
            $output .= $out;
        }
        openssl_free_key($keyId);
        return $output;
    }


	/**
	 * 格式化私钥文件
	 */
	static function formatKey($key, $note = 0) {
			$notice = 'PRIVATE';
			if ($note) $notice = 'PUBLIC';
	        $fKey = "-----BEGIN $notice KEY-----\n";
	        $fKey .= chunk_split($key, 64, "\n");
	        $fKey .= "-----END $notice KEY-----\n";
	        return $fKey;
	}

	 /**
     * 加密是获取最大加密长度
     *根据key的内容获取最大加密lock的大小，兼容各种长度的rsa keysize（比如1024,2048）
     * 对于1024长度的RSA Key，返回值为117
     * @param $keyRes
     * @return float
     */
    public static function getMaxEncryptBlockSize($keyRes){
        $keyDetail = openssl_pkey_get_details($keyRes);
        $modulusSize = $keyDetail['bits'];
        return $modulusSize/8 - 11;
    }


    /**
     * 解密时获取最大解密block的大小
     * 根据key的内容获取最大解密block的大小，兼容各种长度的rsa keysize（比如1024,2048）
     * 对于1024长度的RSA Key，返回值为128
     * @param $keyRes
     * @return float
     */
    public static function getMaxDecryptBlockSize($keyRes){
        $keyDetail = openssl_pkey_get_details($keyRes);
        $modulusSize = $keyDetail['bits'];
        return $modulusSize/8;
    }
}

/* 显示当前的内部字符编码*/
echo "显示当前的内部字符编码";
echo mb_internal_encoding();
echo "<br/>";


$str = '72D23397A0225BEDA4E658ECEA98AD1ACTios526e745a6a9a4864ac0f2d2a80dfcc1e';
$signature = Rsa::sign($str);
var_dump(Rsa::verify($str, $signature), $signature, mb_detect_encoding($signature), 
	//json_encode($signature),  json_last_error(), 
	bin2hex($signature));

echo "<br/>",  "<br/>";

echo '公钥加密->私钥解密:每次加密后的数据不同';
echo "<br/>";
for ($i=0;$i < 5; $i++) {
    $en = Rsa::encrypt($str);
    echo "<br/>";
    var_dump($en);
    var_dump( Rsa::decrypt($en));
}



echo "<br/>",  "<br/>";
echo '私钥加密->公钥解密:每次加密后的数据相同';

echo "<br/>";

for ($i=0;$i < 5; $i++) {
    $en1 = Rsa::encryptByPri($str);
    echo "<br/>";
    var_dump($en1);
    var_dump(Rsa::decryptByPub($en1));
}
